/*
 * enc_monitor.c
 *
 *  Created on: 2018年10月16日
 *  Author: Degang.Wu (windragon@126.com)
 *  Desc:
 */


#include "public.h"
#include "enc_save.h"
#include "slave_client.h"
#include "master_srv.h"
#include "../rtc/hi_rtc.h"

using namespace hiapp;

#define ENC_SAVE_CFG_PERIOD		2	// seconds

void load_mst_chl_testdata(int i)
{
	if (i < 0 || i >= ENC_TOTAL_CHLMAX)
	{
		return;
	}
	if (!enc_is_master())
	{
		return;
	}
	if (NULL == g_encset_mst)
	{
		return;
	}

	stENC_CHLSET& chlset = g_encset_mst->enc_chls[i];

	stENC_VIDSET& video = chlset.encchl_vid;
	video.vid_bitrate_kb = video.vid_bitrate_max = video.vid_bitrate_min = 1024;
	video.vid_codec = BWENC_VID_CODEC_H264;
	video.vid_dar = BWENC_VID_DAR_16_9;
	video.vid_fpsden = 1;
	video.vid_fpsnum = 25;
	video.vid_gopsize = 25;
	video.vid_width = 1920;
	video.vid_height = 1080;
	video.vid_level = 51;
	video.vid_profile = BWENC_VID_PROFILE_HIGH;
	video.vid_rctype = BWENC_VID_RC_CBR;

	stENC_AUDSET& audio = chlset.encchl_aud;
	audio.aud_bitrate_kb = 64;
	audio.aud_channle = 2;
	audio.aud_codec = BWENC_AUD_CODEC_AAC_HE;
	audio.aud_smp_fmt = BWENC_AUD_SMPFMT_S16;
	audio.aud_smp_rate = 48000;
	audio.aud_vol = 100;


	chlset.encchl_setvsion++;
}

void load_slv_chl_testdata(int i)
{

	if (i < 0 || i >= ENC_MAX_CHL)
	{
		return;
	}
	if (enc_is_master())
	{
		return;
	}
	if (NULL == g_encset_slv)
	{
		return;
	}

	BW_INFO("load slv test data, channel[%d]\n", i);
	stENC_CHLSET& chlset = g_encset_slv->enc_chls[i];

	stENC_VIDSET& video = chlset.encchl_vid;
	video.vid_bitrate_kb = video.vid_bitrate_max = video.vid_bitrate_min = 1024;
	video.vid_codec = BWENC_VID_CODEC_H264;
	video.vid_dar = BWENC_VID_DAR_16_9;
	video.vid_fpsden = 1;
	video.vid_fpsnum = 25;
	video.vid_gopsize = 25;
	video.vid_width = 1920;
	video.vid_height = 1080;
	video.vid_level = 51;
	video.vid_profile = BWENC_VID_PROFILE_HIGH;
	video.vid_rctype = BWENC_VID_RC_CBR;

	stENC_AUDSET& audio = chlset.encchl_aud;
	audio.aud_bitrate_kb = 64;
	audio.aud_channle = 2;
	audio.aud_codec = BWENC_AUD_CODEC_AAC_HE;
	audio.aud_smp_fmt = BWENC_AUD_SMPFMT_S16;
	audio.aud_smp_rate = 48000;
	audio.aud_vol = 100;

	stENC_OSDSET& osd = chlset.encchl_osd[0];
	osd.osd_enable = 1;
	osd.osd_type = BWENC_OSD_TYPE_TEXT;
	stENC_SUBSET& sub = osd.osd_cfg.osd_sub;
	snprintf((char*)sub.sub_content, sizeof(sub.sub_content), "%s", "成都邦威思创");
	sub.sub_backcolor = 0xffffff;
	sub.sub_fontcolor = 0x000000;
	sub.sub_fontsize = 32;
	sub.sub_fontstyle = 1;
	sub.sub_width = 400;
	sub.sub_height = 100;
	sub.sub_x = 20;
	sub.sub_y = 30;
	snprintf((char*)sub.sub_font, sizeof(sub.sub_font), "%s", "黑体");

	chlset.encchl_setvsion++;
}

static void monitor_master()
{
	char app_name[MAX_PATH];
	snprintf(app_name, sizeof(app_name), "%s/%s", u::Util::module_folder(), u::Util::module_name());

	BW_INFO("MASTER monitor is running");

	// init encoder channel dst ip & port
	struct in_addr addr;
	inet_aton(ENC_CHL_OUT_IP, &addr);
	addr.s_addr = ntohl(addr.s_addr);
	for (int i = 0; i < ENC_MAX_SUB_BOARD; i++)
	{
		U32 port = ENC_CHL_OUT_PORT;
		for (int j = 0; j < ENC_MAX_CHL; j++)
		{
			stENC_CHLSET& chlset = g_encset_mst->enc_chls[i*ENC_MAX_CHL+j];
			chlset.encchl_output.ethio_dipaddr = addr.s_addr;
			chlset.encchl_output.ethio_dipport = port++;
		}
		addr.s_addr++;
	}

	// Load test data
#ifdef __DEBUG_HIENC
	for (int i = 0; i < 4; i++)
	{
		g_encset_mst->sboard[i].reg_flag = 1;
		g_encset_mst->sboard[i].status = 1;
	}
	BW_INFO("Load test master channel");
	load_mst_chl_testdata(0);
	load_mst_chl_testdata(4);
	load_mst_chl_testdata(8);
	load_mst_chl_testdata(12);
#endif

	MasterSrv* pServer = new MasterSrv(ENC_MASTER_PORT);
	pServer->begin();//开启各种线程
	//NULL;

	while (enc_is_running())
	{
		if (g_encset_mst)
		{
			if (g_encset_mst->enc_savevsion != g_encset_mst->enc_setvsion)
			{
				shrmem_enc_save_mst(g_encset_mst);
				g_encset_mst->enc_savevsion = g_encset_mst->enc_setvsion;
			}

			for (int i = 0; i < ENC_TOTAL_CHLMAX; i++)
			{
				stENC_CHLSET& chlset = g_encset_mst->enc_chls[i];
				if (chlset.encchl_savevsion != chlset.encchl_setvsion)
				{
					shrmem_encchl_save(&chlset, i);
					chlset.encchl_savevsion = chlset.encchl_setvsion;
				}
			}
		}

		sleep(1);
	}

	if (pServer)
	{
		pServer->stop();
		delete pServer;
		pServer = NULL;
	}

	BW_INFO("MASTER monitor quit");
}


static void monitor_slave()
{
#ifdef __SLAVE
	hienc_rtc_init();
#endif

	char app_name[MAX_PATH];
	snprintf(app_name, sizeof(app_name), "%s/%s", u::Util::module_folder(), u::Util::module_name());
	char	cmd[SZ_1K];

	BW_INFO("SLAVE monitor is running");

#ifdef __DEBUG_HIENC
	BW_INFO("Load test slave channel(0)");
	load_slv_chl_testdata(0);
#endif

	// init socket
	SlaveClient* pSlave = new SlaveClient(ENC_SLAVE_PORT);
	if (pSlave)
	{
		pSlave->begin();
	}

	for ( int i = 0; i < ENC_MAX_CHL; i++)
	{
		if (g_encset_slv->enc_chls[i].encchl_procpid > 0)
		{
			kill(g_encset_slv->enc_chls[i].encchl_procpid, SIGTERM);
			g_encset_slv->enc_chls[i].encchl_procpid = 0;
		}
	}

	while (enc_is_running())
	{
		for (int i = 0; i < ENC_MAX_CHL; i++)
		{
			if (g_encset_slv->enc_chls[i].encchl_isrun)
			{
				if (g_encset_slv->enc_chls[i].encchl_procpid == 0)
				{
					snprintf(cmd, sizeof(cmd), "%s -idx %d -cfgpath %s &", app_name, i, g_cfgpath);
					u::Util::shell_exec(cmd, NULL, NULL);
				}
				else
				{
					// check alive
					if(kill(g_encset_slv->enc_chls[i].encchl_procpid, 0) != 0)
					{
						g_encset_slv->enc_chls[i].encchl_procpid = 0;
					}
				}
			}
		}

		sleep(1);
	}

	for ( int i = 0; i < ENC_MAX_CHL; i++)
	{
		if (g_encset_slv->enc_chls[i].encchl_procpid > 0)
		{
			kill(g_encset_slv->enc_chls[i].encchl_procpid, SIGTERM);
			g_encset_slv->enc_chls[i].encchl_procpid = 0;
		}
		g_encset_slv->enc_chls[i].encchl_isrun = 0;
	}


	if (pSlave)
	{
		pSlave->stop();
		delete pSlave;
		pSlave = NULL;
	}
	BW_INFO("SLAVE monitor quit");
}

int hienc_monitor(int argc, char**argv)
{
	// init ram log path
	char cmd[SZ_1K];
	if (!u::io::File::exists(HIENC_RAM_LOG_PATH))
	{
		snprintf(cmd, sizeof(cmd), "mkdir -p %s", HIENC_RAM_LOG_PATH);
		u::Util::shell_exec(cmd, NULL, NULL);
	}
	snprintf(cmd, sizeof(cmd), "umount %s; mount -t ramfs none %s -o maxsize=20000", HIENC_RAM_LOG_PATH, HIENC_RAM_LOG_PATH);
	u::Util::shell_exec(cmd, NULL, NULL);

#ifdef __DEBUG_HIENC
	u::sys::OS::set_coredump_path(u::Util::module_folder());
	BW_INFO("DEBUG VER, set core path to [%s]\n", u::Util::module_folder());

	signal(SIGINT, enc_sig_handler);
	BW_INFO("DEBUG VER, set signal(SIGINT)\n");
#endif
	signal(SIGINT, enc_sig_handler);
	BW_INFO("DEBUG VER, set signal(SIGINT)\n");

	BW_INFO("%s MONITOR====>start..., config path = %s, %s\n", u::Util::module_name(), g_cfgpath, enc_is_master() ? "MASTER" : "SLAVE");
	BW_INFO("MASTER ipaddr = [%s]\n", hienc_get_priv_mst_ipaddr());
	char slvipaddrs[SZ_1K];
	memset(slvipaddrs, 0, sizeof(slvipaddrs));
	for (int i = 0; i < ENC_MAX_SUB_BOARD; i++)
	{
		snprintf(slvipaddrs+strlen(slvipaddrs), sizeof(slvipaddrs)-strlen(slvipaddrs), "idx.%d-%s", i, hienc_get_priv_slv_ipaddr(i));
		if (i < (ENC_MAX_SUB_BOARD - 1))
		{
			snprintf(slvipaddrs+strlen(slvipaddrs), sizeof(slvipaddrs)-strlen(slvipaddrs), ", ");
		}
	}
	BW_INFO("SLAVE ipaddr = [%s]\n", slvipaddrs);

	
	if(shrmem_init(1)==0)
	{
		BW_INFO("BWHIENCAPP MONITOR====>shrmem_init failed!\n");
		shrmem_uninit();
		return 0;
	}
	else
	{
		BW_INFO("BWHIENCAPP MONITOR====>shrmem_init OK!\n");
	}

	if (enc_is_master())
	{
		monitor_master();
	}
	else
	{
		monitor_slave();
	}

	shrmem_uninit();
	return 0;
}
